#include "TDAServidorInseguro.h"
#include "logdebug.h"
#include "listasimple.h"
#include "cola.h"
#include <string.h>

/* TODAS LAS PRIMITIVAS Y FUNCIONES AUXILIARES PROBADAS Y FUNCIONANDO*/

/*Comienzo de Funciones Auxiliares*/

/*
 * Copia el contenido de una lista en otra
 *
 * Parametros:
 * Origen	ListaSimple de Origen
 * Destino  pListaSimple de Destino
 *
 * Valor de retorno:
 * Devuelve TRUE si se pudo copiar y FALSE si no pudo.
 *
 * PRE: TlistaSimple de Origen y destino Creadas y válidas. Destino ESTA VACIA.
 * POST: Se ha copiado la lista de Origen en Destino. Se puede eliminar la lista Origen con tranquilidad.
 *
 */
int Copiar_Lista(TListaSimple *Destino, TListaSimple Origen){
    Telem elem;
    int mov_ok=TRUE;
    if(ls_Vacia(Origen)==FALSE){
        ls_MoverCorriente(&Origen,LS_PRIMERO);
        while(mov_ok==TRUE){
            ls_ElemCorriente(Origen,&elem);
            if(ls_Vacia(*Destino))
                ls_Insertar(Destino,LS_PRIMERO,&elem);
            else
                ls_Insertar(Destino,LS_SIGUIENTE,&elem);
            mov_ok=ls_MoverCorriente(&Origen,LS_SIGUIENTE);
        }
        return TRUE;
    }
    else return FALSE;
}

/*
 * Cuenta la cantidad de correos en cola
 *
 * Parametros:
 * Cola cola a contar correos
 *
 * Valor de retorno:
 * Devuelve la cantidad de correos en cola.
 *
 * PRE: Cola creada. Los elemenentos de la cola son del tipo TDACorreo.
 * POST: Se ha obtenido la cantidad de correos en cola.
 *
 */
int contar_correos(TCola *Cola) {
    int cantidad=0;
    TDACorreo elem;
    crearCorreo(&elem);
    strcpy(elem.Asunto,"STOP");
    strcpy(elem.Cuerpo,"STOP");
    C_Agregar(Cola,&elem);
    do{
        crearCorreo(&elem);
        C_Sacar(Cola,&elem);
        if((strcmp(elem.Asunto,"STOP")!=0) && (strcmp(elem.Cuerpo,"STOP")!=0)) {
            C_Agregar(Cola,&elem);
            cantidad++;
        }
    }while((strcmp(elem.Asunto,"STOP")!=0) && (strcmp(elem.Cuerpo,"STOP")!=0));
    return cantidad;
}

/* Fin de Funciones Auxiliares */


void crearServidor(TDAServidorInseguro* servidor) {

    /*Creo un correo vacio para todos los MAX_SERVER_CONTENT correos del servidor*/
    C_Crear(&servidor->correos,sizeof(TDACorreo));
    servidor->cantidadCorreos = 0;
    C_Crear(&servidor->log,MAX_LOG_LEN);
}

void destruirServidor(TDAServidorInseguro* servidor) {

     /*Elimino el contenido de todos los MAX_SERVER_CONTENT correos del servidor*/
     if(C_Vacia(servidor->correos)==FALSE)
        C_Vaciar(&servidor->correos);
     servidor->cantidadCorreos = 0;
     if (C_Vacia(servidor->log)==FALSE)
        C_Vaciar(&servidor->log);
}

int agregarCorreo(TDAServidorInseguro* servidor, TDACorreo correo) {
    TDACorreo correoNuevo;
    char aux[MAX_BODY_SIZE], log_text[MAX_LOG_LEN];
    time_t date;
    struct tm *tmPtr;
    TListaSimple aux2;
    Telem elem;
    ls_Crear(&aux2,sizeof(elem));
    int mov_ok=TRUE;

    /*Seteo la hora en el texto de log*/
    date=time(NULL);
    tmPtr=localtime(&date);
    strcpy(log_text,"\0");
    strftime(log_text,MAX_LOG_LEN,"%d %b %Y %H:%M:%S ", tmPtr);

    /*Incremento en 1 la cantidad de correos en el servidor y creo un correo para agregar */
    servidor->cantidadCorreos = servidor->cantidadCorreos +1;
    crearCorreo(&correoNuevo);

    /*Copio el contenido del correo al servidor*/
    getRemitente(correo,aux);
    if(strcmp(aux,"\0")==0) {
        logmacro("%s\n", "Servidor> SE INTENTO AGREGAR UN CORREO SIN REMITENTE");
        return 1;
    }
	setRemitente(&correoNuevo,aux);
	/*Seteo el destinatario en el texto del log*/
	strcat(log_text,aux);
	strcat(log_text," envió el correo ");
	getDestinatarios(correo,&aux2);
	if(ls_Vacia(aux2)==FALSE) {
	    ls_MoverCorriente(&aux2,LS_PRIMERO);
	    while(mov_ok==TRUE) {
	        ls_ElemCorriente(aux2,&elem);
	        if(ls_Vacia(correoNuevo.Para))
                ls_Insertar(&correoNuevo.Para,LS_PRIMERO,&elem);
            else
                ls_Insertar(&correoNuevo.Para,LS_SIGUIENTE,&elem);
	        mov_ok=ls_MoverCorriente(&aux2,LS_SIGUIENTE);
	    }
	}
    else {
	    logmacro("%s\n", "Servidor> SE INTENTO AGREGAR UN CORREO SIN DESTINATARIOS");
	    return 1;
	}
	strcpy(aux, "\0");
	getAsunto(correo,aux);
	setAsunto(&correoNuevo,aux);
	/*Seteo el asunto en el texto del log*/
	strcat(log_text,aux);
	setFechaHoraEnviado(&correoNuevo,getFechaHoraEnviado(correo));
	strcpy(aux, "\0");
	getTextoCuerpo(correo,aux);
	setTextoCuerpo(&correoNuevo,aux);
	strcpy(correoNuevo.nombre_del_archivo, correo.nombre_del_archivo);
	/*Logeo el envio*/
	C_Agregar(&servidor->log,&log_text);
	/*Agrego el correo a la cola de correos en el servidor*/
	C_Agregar(&servidor->correos,&correoNuevo);
	return 0;
}

int obtenerProximoCorreo(TDAServidorInseguro* servidor, char* destinatario, TDACorreo* correo) {
   int i=1,mov_ok;
   time_t date;
   struct tm *tmPtr;
   char log_text[MAX_LOG_LEN];
   Telem elem;
   int next_found=FALSE, to_delete;
   int cantidad_correos=contar_correos(&servidor->correos);
   TDACorreo correoNuevo;

    /*Busco si hay correos en el servidor para este destinatario*/
    while((next_found==FALSE) && (i<=cantidad_correos)){
        to_delete=TRUE;
        crearCorreo(&correoNuevo);
        C_Sacar(&servidor->correos,&correoNuevo);
        if(ls_Vacia(correoNuevo.Para)==FALSE){
            ls_MoverCorriente(&correoNuevo.Para,LS_PRIMERO);
            mov_ok=TRUE;
            while(mov_ok==TRUE){
                ls_ElemCorriente(correoNuevo.Para,&elem);
                /*Si hay un correo no recibido para ese destinatario lo recibo*/
                if((strcmp(elem.direccion,destinatario)==0) && (elem.estado==NO_RECIBIDO)) {
                    setRemitente(correo,correoNuevo.De);
                    ls_Vaciar(&correo->Para);
                    Copiar_Lista(&correo->Para,correoNuevo.Para);
                    setAsunto(correo,correoNuevo.Asunto);
                    setTextoCuerpo(correo,correoNuevo.Cuerpo);
                    setFechaHoraEnviado(correo,correoNuevo.Fecha);
                    strcpy(correo->nombre_del_archivo,correoNuevo.nombre_del_archivo);
                    /*Logeo la recepción*/
                    date=time(NULL);
                    tmPtr=localtime(&date);
                    strcpy(log_text, "\0");
                    strftime(log_text,MAX_LOG_LEN,"%d %b %Y %H:%M:%S ", tmPtr);
                    strcat(log_text, destinatario);
                    strcat(log_text," recibió el correo ");
                    strcat(log_text, correo->Asunto);
                    C_Agregar(&servidor->log,&log_text);
                    /*Lo marco como recibido*/
                    elem.estado=RECIBIDO;
                    ls_ModifCorriente(&correoNuevo.Para,&elem);
                    next_found=TRUE;
                }
                if(elem.estado==NO_RECIBIDO) /*Si hay al menos uno NO_RECIBIDO no lo elimino*/
                    to_delete=FALSE;
                mov_ok=ls_MoverCorriente(&correoNuevo.Para,LS_SIGUIENTE);
            }
            if(to_delete==FALSE) {
                C_Agregar(&servidor->correos,&correoNuevo);
            }
        }
        i++;
    }

    /*Devuelvo si se encontro o no un proximo correo*/
    return next_found;
}

int obtenerCorreos(TDAServidorInseguro *servidor, char *dest, TCola *correos) {
    TDACorreo correoRecibido;
    crearCorreo(&correoRecibido);
    int msg=FALSE;

    while(obtenerProximoCorreo(servidor,dest,&correoRecibido)==TRUE) {
        C_Agregar(correos,&correoRecibido);
        msg=TRUE;
        crearCorreo(&correoRecibido);
        }
    return msg;
}


int escribirLog(TDAServidorInseguro *servidor, FILE* archivo) {
    char log_text[MAX_LOG_LEN];

    /*Voy sacando cada linea de la cola de Log y la escribo en el archivo, hasta que no tenga elementos*/
    while(C_Vacia(servidor->log)==FALSE) {
        C_Sacar(&servidor->log, &log_text);
        fprintf(archivo,"%s\n",log_text);
    }
    return FALSE;
}
